package org.example.springbootproject.config;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.Base64;
import java.util.Map;
import java.util.UUID;

@Component
public class KaptchaUtil {
    private static final Logger log = LoggerFactory.getLogger(KaptchaUtil.class);
    private DefaultKaptcha kaptchaProducer;

    // 存储验证码 token、文本和时间戳的映射
    private final Map<String, CaptchaData> captchaStore = new ConcurrentHashMap<>();

    // 验证码有效期（毫秒）
    private static final long CAPTCHA_EXPIRATION = TimeUnit.MINUTES.toMillis(5);

    /**
     * 生成 Base64 编码的验证码图片及对应的 token
     * @return 包含 token 和 base64 图片数据的 Map
     */
    public Map<String, String> generateBase64Captcha() {
        String captchaText = kaptchaProducer.createText();
        BufferedImage image = kaptchaProducer.createImage(captchaText);
        String token = UUID.randomUUID().toString();
        
        // 存储验证码数据和生成时间戳
        captchaStore.put(token, new CaptchaData(captchaText, System.currentTimeMillis()));

        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            ImageIO.write(image, "PNG", outputStream);
            
            String base64Image = Base64.getEncoder().encodeToString(outputStream.toByteArray());

            Map<String, String> response = new HashMap<>();
            response.put("token", token);
            response.put("base64Image", "data:image/png;base64," + base64Image);
            return response;
        } catch (IOException e) {
            throw new RuntimeException("Error generating captcha image", e);
        }
    }

    /**
     * 验证用户输入的验证码是否正确
     * @param token 用于查找存储的验证码
     * @param userInput 用户输入的验证码
     * @return 验证结果
     */
    public boolean validateCaptcha(String token, String userInput) {
        if (token == null || userInput == null) {
            log.warn("Token or user input is null");
            return false;
        }

        CaptchaData captchaData = captchaStore.get(token);
        
        if (captchaData == null) {
            log.warn("Captcha not found for token: {}", token);
            return false;
        }

        // 检查验证码是否过期
        if (isCaptchaExpired(captchaData)) {
            captchaStore.remove(token);
            log.warn("Captcha expired for token: {}", token);
            return false;
        }

        boolean isValid = userInput.equalsIgnoreCase(captchaData.text);
        
        if (isValid) {
            captchaStore.remove(token); // 验证成功后清除 token
            log.info("Captcha validation successful for token: {}", token);
        } else {
            log.warn("Captcha validation failed for token: {}, input: {}", token, userInput);
        }
        
        return isValid;
    }

    /**
     * 检查验证码是否过期
     */
    private boolean isCaptchaExpired(CaptchaData captchaData) {
        long currentTime = System.currentTimeMillis();
        return currentTime - captchaData.timestamp > CAPTCHA_EXPIRATION;
    }

    @PostConstruct
    public void init() {
        // 配置Kaptcha
        Properties properties = new Properties();
        properties.put("kaptcha.image.width", "150");
        properties.put("kaptcha.image.height", "60");
        properties.put("kaptcha.textproducer.font.size", "36");
        properties.put("kaptcha.textproducer.char.length", "4");
        
        Config config = new Config(properties);
        kaptchaProducer = new DefaultKaptcha();
        kaptchaProducer.setConfig(config);
        
        log.info("Kaptcha configured successfully");
    }

    /**
     * 内部类用于存储验证码文本和生成时间
     */
    private static class CaptchaData {
        String text;
        long timestamp;

        CaptchaData(String text, long timestamp) {
            this.text = text;
            this.timestamp = timestamp;
        }
    }
}